import * as THREE from "three";
import { SketchBase } from "fast-three-sketch";
import { CargoPoint, Ground } from "../objects";
import { Cargo } from "../objects/Cargo";
import { shelfManager } from "../objects/ShelfManager";
import { Repertory } from "./Repertory";

export class World extends SketchBase {

    constructor() {

        super(document.getElementById("app"), { antialias: true, logarithmicDepthBuffer: true });

        this.initTransformControls();

        this.camera.position.set(20, 40, 20);

        this.setupLights();

        this.createGround();

        const repertory = new Repertory(this);

        ////////////////////////////////////////////////////////////////////


        repertory.createShelf(`货架${1}`, "shape2");
        repertory.createShelf(`货架${2}`, "shape1", new THREE.Vector3(0, 0, -3));

        for (let i = 0; i < 50; i++) {

            const cargo = new Cargo("硅胶1", 100);
            cargo.init(0.3, 0.3, 0.3);
            repertory.addCargo(cargo);

        }


        /////////////////////////////////////////////////////

        const transformControls = this.transformControls;
        transformControls.setMode("translate");


        let selected: THREE.Object3D = null;
        let nearestCargoPoint: CargoPoint = null;
        let lastCargoPoint: CargoPoint = null;

        this.raycast("click", repertory.getAllCargoObjects(), intersections => {
            if (intersections.length) {
                const object = intersections[0].object;
                transformControls.attach(object);
                this.controls.enabled = false;
                selected = object;
            } else {
                transformControls.detach();
                this.controls.enabled = true;
                selected = null;
            }
        });

        transformControls.addEventListener("translate", () => {

            const vec = new THREE.Vector3();
            selected.getWorldPosition(vec);

            const result = shelfManager.nearestCargoPoint(vec, 2);

            if (result.length) {

                const vec3 = result[0][0];

                nearestCargoPoint = shelfManager.getCargoPoint(vec3);

            } else {

                nearestCargoPoint = null;

            }

        });

        transformControls.addEventListener("dragging-changed", e => {

            const cargo = selected.userData.cargo as Cargo;

            if (e.value) {

                lastCargoPoint = cargo.cargoPoint;

                cargo.object.getWorldPosition(cargo.object.position);
                cargo.removeFromShelf();
                this.add(cargo.object);

            } else {

                if (nearestCargoPoint) {
                    selected.position.set(0, cargo.height / 2, 0);
                    cargo.addToShelf(nearestCargoPoint.shelf, nearestCargoPoint);
                } else {
                    selected.position.set(0, cargo.height / 2, 0);
                    cargo.addToShelf(lastCargoPoint.shelf, lastCargoPoint);
                }

            }

        });

        this.animate();

    }

    createGround() {
        const texture = new THREE.TextureLoader().load("./textures/i.png");

        const ground = new Ground({
            map: texture,
            wrapS: 5,
            wrapT: 10,
            gaussian: true,
            smooth: 0.5  // 地面光滑系数，0完全粗糙，不反射，1完全镜面，
        });
        ground.init(10, 20);
        this.add(ground);

    }

    setupLights() {
        this.add(new THREE.AmbientLight(new THREE.Color(0xffffff), 0.8));
        const directionalLight = new THREE.DirectionalLight(new THREE.Color(0xffffff), 0.3);
        directionalLight.position.set(1, 1, 1);
        this.add(directionalLight);
    }
}